﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using winAppGame.model;
using winAppGame.service;

namespace winAppGame.service.rulechecker
{
    /// <summary>
    /// author:zuowenjun
    /// copyright:www.zuowenjun.cn
    /// 对子、2的顺子出牌规则检查器
    /// </summary>
    public class DoublePaiRuleChecker : PaiRuleChecker
    {
        public override int ForBaseCount => 2;

        public override int ForIncrementCount => 2;

        public override List<PaiRuleType.PaiRuleTypeItem> ForRuleTypes => BuildPaiRuleTypeItems(PaiRuleType.Double, PaiRuleType.DoubleMore);

        protected override PaiRuleCheckResult DoCheckAllowShowPais(List<Pai> selectedPais, List<Pai> lastShowPais, PaiRuleCheckContext checkContext)
        {
            var compare = selectedPais.Min().CompareTo(lastShowPais.Min());
            if (compare > 0)
            {
                return PaiRuleCheckResult.Pass(checkContext.SelectedRuleType);
            }
            return PaiRuleCheckResult.Failed("出牌数值<=上家已出牌数值！");
        }

        protected override PaiRuleCheckResult DoCheckSelectedPais(List<Pai> selectedPais, PaiRuleCheckContext checkContext)
        {
            var paiDic = ConvertToDictionary(selectedPais);
            int doublePaiCount = paiDic.Where(p => p.Value == 2).Count();

            if (doublePaiCount * 2 != selectedPais.Count || doublePaiCount == 2)
            {
                //1对 或 3对及以上均可以
                return PaiRuleCheckResult.Failed("出牌张数不正确，要么2张，要么6张及以上！");
            }

            var paiOrderList = paiDic.Where(p => p.Value == 2).Select(p => p.Key).OrderBy(p => p).ToList();
            if (!IsSerial(paiOrderList))
            {
                return PaiRuleCheckResult.Failed("非连续！");
            }
            checkContext.SelectedRuleType = doublePaiCount > 1 ? PaiRuleType.DoubleMore : PaiRuleType.Double;
            return PaiRuleCheckResult.Pass(checkContext.SelectedRuleType);
        }

        public override PaiRuleCheckResult AutoSelectPais(IDictionary<Pai, int> groupPais, IEnumerable<Pai> lastShowPais, PaiRuleType.PaiRuleTypeItem showRuleType)
        {
            var doubleGroupPais = groupPais.Where(kv => kv.Value >= 2).OrderBy(kv => kv.Key).Select(kv => kv);

            if (lastShowPais.HasItem())
            {
                var lastShowDoublePais = ConvertToDictionary(lastShowPais).Where(kv => kv.Value == 2).AsEnumerable();
                var lastShowMinPai = lastShowDoublePais.Min(kv => kv.Key);
                doubleGroupPais = doubleGroupPais.Where(kv => kv.Key > lastShowMinPai).OrderBy(kv => kv.Key).Select(kv => kv);
                return DoAutoSelectPais(doubleGroupPais, lastShowDoublePais, showRuleType);
            }
            else
            {
                return DoAutoSelectPais(doubleGroupPais, null, showRuleType);
            }
        }



        private PaiRuleCheckResult DoAutoSelectPais(IEnumerable<KeyValuePair<Pai, int>> doubleGroupPais, IEnumerable<KeyValuePair<Pai, int>> lastShowDoublePais, PaiRuleType.PaiRuleTypeItem showRuleType)
        {
            if (!doubleGroupPais.HasItem() || (lastShowDoublePais.HasItem() && doubleGroupPais.Count() < lastShowDoublePais.Count()))
            {
                return PaiRuleCheckResult.Failed("要不起！");
            }

            Pai prePai = null;
            int forIndex = 0;
            Dictionary<Pai, int> okPais = new Dictionary<Pai, int>();
            int lowShowPaisCount = lastShowDoublePais.HasItem() ? lastShowDoublePais.Count() : 3;

            if (showRuleType == PaiRuleType.Double)
            {
                var selectedPaiKv = doubleGroupPais.OrderBy(kv => kv.Value).First();
                okPais[selectedPaiKv.Key] = 2;
                return PaiRuleCheckResult.Pass(PaiRuleType.Double, okPais);
            }

            foreach (var kv in doubleGroupPais)
            {
                forIndex++;

                if (prePai != null)
                {
                    if (prePai + 1 != kv.Key)
                    {
                        if (forIndex >= doubleGroupPais.Count() || forIndex > lowShowPaisCount)
                        {
                            //若最后一张牌 或 已达到连续2个3张及以上，则中止
                            break;
                        }
                        //否则重置，重新检测连续
                        okPais.Clear();
                        forIndex = 1;
                    }
                    else if (lastShowDoublePais.HasItem() && okPais.Count() == lastShowDoublePais.Count())
                    {
                        //若满足上家出牌张数则中止
                        break;
                    }
                }

                prePai = kv.Key;
                okPais.Add(kv.Key, 2);
            }

            if (okPais.Count() < lowShowPaisCount)
            {
                //如果32张的小于3个连续 ，则说明无法构成2+2+N的出牌规则
                return PaiRuleCheckResult.Failed("要不起！");
            }

            return PaiRuleCheckResult.Pass(PaiRuleType.DoubleMore, okPais);

        }


    }
}
